<template>
  <div>
    <Card title="场景查询" :bordered="false" :dis-hover="true">
      <div slot="extra">
        <Button
          size="small"
          type="primary"
          icon="ios-search"
          class="card-extra-item"
          @click="search"
          >查询</Button
        >
        <Button
          size="small"
          type="default"
          icon="ios-refresh"
          class="card-extra-item"
          @click="reset"
          >重置</Button
        >
        <Button
          size="small"
          type="text"
          :icon="showMore ? 'ios-arrow-up' : 'ios-arrow-down'"
          class="card-extra-item"
          @click="showMore = !showMore"
          >{{ showMore ? "收起" : "展开" }}</Button
        >
      </div>
      <Form
        inline
        label-position="right"
        :label-width="120"
        :model="searchParams"
      >
        <Row>
          <Col span="6">
            <FormItem label="所属项目" prop="project">
              <Select v-model="searchParams.project" filterable clearable>
                <Option
                  v-for="item in projects"
                  :value="item.id"
                  :key="item.id"
                  >{{ item.name }}</Option
                >
              </Select>
            </FormItem>
          </Col>
          <Col span="6">
            <FormItem label="场景名称">
              <Input
                clearable
                placeholder="请输入场景名称"
                v-model="searchParams.name"
              />
            </FormItem>
          </Col>
          <Col span="6">
            <FormItem label="重要级别">
              <Select v-model="searchParams.level" multiple>
                <Option
                  v-for="(item, index) in levels"
                  :value="item.value"
                  :label="item.label"
                  :key="index"
                ></Option>
              </Select>
            </FormItem>
          </Col>
          <Col span="6">
            <FormItem label="场景创建人">
              <Select
                v-model="searchParams.creator"
                multiple
                filterable
                :max-tag-count="2"
              >
                <Option
                  v-for="(item, index) in users"
                  :value="item.id"
                  :label="item.real_name"
                  :key="index"
                ></Option>
              </Select>
            </FormItem>
          </Col>
        </Row>
        <CollapseTransition>
          <div v-show="showMore">
            <Row>
              <Col span="6">
                <FormItem label="私有环境状态">
                  <Select v-model="searchParams.enable_private_env" clearable>
                    <Option value="true">开启</Option>
                    <Option value="false">关闭</Option>
                  </Select>
                </FormItem>
              </Col>
              <Col span="6">
                <FormItem label="场景状态">
                  <Select v-model="searchParams.status" clearable>
                    <Option value="INITIAL">初始状态</Option>
                    <Option value="PASS">全部通过</Option>
                    <Option value="PARTIAL_PASS">部分通过</Option>
                    <Option value="FAIL">全部失败</Option>
                  </Select>
                </FormItem>
              </Col>
            </Row>
          </div>
        </CollapseTransition>
      </Form>
    </Card>
    <Card title="场景列表" :bordered="false" :dis-hover="true">
      <div slot="extra">
        <span class="card-extra-item">
          <Icon
            size="24"
            :color="statusColor['INITIAL']"
            type="ios-leaf"
          />初始状态
        </span>
        <span class="card-extra-item">
          <Icon
            size="24"
            :color="statusColor['PASS']"
            type="ios-leaf"
          />全部通过
        </span>
        <span class="card-extra-item">
          <Icon
            size="24"
            :color="statusColor['PARTIAL_PASS']"
            type="ios-leaf"
          />部分通过
        </span>
        <span class="card-extra-item">
          <Icon
            size="24"
            :color="statusColor['FAIL']"
            type="ios-leaf"
          />全部失败
        </span>
        <Button
          class="card-extra-item"
          size="small"
          type="primary"
          @click="createTestsuite = true"
          >创建场景</Button
        >
        <Button
          class="card-extra-item"
          size="small"
          type="primary"
          @click="handleBatchExecTestsuite"
          >批量执行</Button
        >
        <Button
          class="card-extra-item"
          size="small"
          type="primary"
          @click="handleExportTestsuite"
          :loading="loading"
          >导出场景</Button
        >
        <Button
          type="primary"
          size="small"
          class="card-extra-item"
          @click="showCreatePeriodicTaskModal"
          >创建定时任务</Button
        >
        <Button
          class="card-extra-item"
          size="small"
          type="error"
          @click="showBatchDeleteTestsuiteModal"
          >删除</Button
        >
      </div>
      <Table
        :columns="testsuiteColumns"
        :data="testsuiteData"
        border
        size="small"
        :tooltip-max-width="500"
        @on-selection-change="selectionChange"
      >
        <template slot-scope="{ row }" slot="project">{{
          row.project.name
        }}</template>
        <template slot-scope="{ row }" slot="testcases">
          <Tag
            :color="item.type === 'HTTP_API' ? 'blue' : 'green'"
            v-for="(item, index) in row.testcases"
            :key="index"
            type="border"
            >{{ item.testcase_name || item.ext_method_name }}</Tag
          >
        </template>
        <template slot-scope="{ row }" slot="enable_private_env">
          <i-switch
            true-color="#13ce66"
            false-color="#ff4949"
            size="large"
            v-model="row.enable_private_env"
            @on-change="switchEnablePrivateEnv(row)"
          >
            <span slot="open">开启</span>
            <span slot="close">关闭</span>
          </i-switch>
        </template>
        <template slot-scope="{ row }" slot="level">
          <Select
            transfer
            v-model="row.level"
            @on-change="changeTestsuiteLevel(row)"
          >
            <div
              slot="prefix"
              size="small"
              :class="
                'levelSelect-prefix levelOption-' + row.level.toLowerCase()
              "
            ></div>
            <Option
              v-for="(item, index) in levels"
              :value="item.value"
              :label="item.label"
              :key="index"
              :class="'levelOption levelOption-' + item.value.toLowerCase()"
            ></Option>
          </Select>
        </template>
        <template slot-scope="{ row }" slot="modifier">{{
          row.modifier.real_name
        }}</template>
        <template slot-scope="{ row }" slot="status">
          <Icon size="24" :color="statusColor[row.status]" type="ios-leaf" />
        </template>
        <template slot-scope="{ row }" slot="action">
          <Button
            size="small"
            type="text"
            style="color: #2d8cf0"
            @click="showCopyTestsuiteModal(row.id)"
            >复制</Button
          >
          <Button
            size="small"
            type="text"
            style="color: #2d8cf0"
            @click="showEditTestsuiteModal(row)"
            >编辑</Button
          >
          <Button
            size="small"
            type="text"
            style="color: #2d8cf0"
            @click="showOrganizeTestcaseModal(row)"
            >场景组织</Button
          >
        </template>
      </Table>
      <Page
        transfer
        :total="page.total"
        :current="page.current"
        :page-size="page.pageSize"
        :page-size-opts="page.pageSizeOpts"
        size="small"
        show-elevator
        show-sizer
        show-total
        prev-text="上一页"
        next-text="下一页"
        style="margin-top: 15px"
        @on-change="change"
        @on-page-size-change="pageSizeChange"
      />
    </Card>
    <PeriodicTaskCreate
      :createPeriodicTask.sync="createPeriodicTask"
      :task.sync="periodicTask"
      :args.sync="periodicTaskArgs"
      :showKwargs="false"
    ></PeriodicTaskCreate>
    <TestsuiteCreate
      :createTestsuite.sync="createTestsuite"
      @initTestsuiteTable="search"
    ></TestsuiteCreate>
    <TestsuiteCopy
      :copyTestsuite.sync="copyTestsuite"
      :testsuite.sync="testsuite"
      @initTestsuiteTable="search"
    >
    </TestsuiteCopy>
    <TestsuiteEdit
      :editTestsuite.sync="editTestsuite"
      @initTestsuiteTable="search"
      :testsuite="testsuite"
    ></TestsuiteEdit>
    <Testsuite2Testcase
      :organizeTestcase.sync="organizeTestcase"
      @initTestsuiteTable="search"
      :testsuite.sync="testsuite"
      :project.sync="project"
    ></Testsuite2Testcase>
    <Modal
      v-model="deleteTestsuiteConfirm"
      title="删除场景"
      width="550"
      :mask-closable="false"
      @on-cancel="handleDeleteTestsuiteConfirmCancel"
    >
      部分场景已与场景集相关联，请选择删除方式
      <div slot="footer">
        <Button
          type="warning"
          @click="handleDeleteTestsuiteConfirmSubmit(false)"
          >只删除未关联场景集的场景</Button
        >
        <Button type="error" @click="handleDeleteTestsuiteConfirmSubmit(true)"
          >删除场景并解绑关联场景集</Button
        >
        <Button type="primary" @click="handleDeleteTestsuiteConfirmCancel"
          >取消</Button
        >
      </div>
    </Modal>
  </div>
</template>

<script>
import PeriodicTaskCreate from "@/view/components/CeleryScheduledTaskService/periodic-task/periodic-task-create";
import {
  getTestsuites,
  batchDeleteTestsuite,
  batchExecTestsuite,
  partialUpdateTestsuite,
  exportTestsuite,
} from "@/api/HttpAutoTestService/testsuite";
import TestsuiteCreate from "./testsuite-create";
import TestsuiteCopy from "./testsuite-copy";
import TestsuiteEdit from "./testsuite-edit";
import Testsuite2Testcase from "./testsuite2testcase";
import CollapseTransition from "_c/collapse-transition/collapse-transition.js";
import { getProjectNames } from "@/api/HttpAutoTestService/project";
import { getUserNames } from "@/api/HttpAutoTestService/user";

export default {
  name: "testsuite",
  components: {
    PeriodicTaskCreate,
    TestsuiteCreate,
    TestsuiteCopy,
    TestsuiteEdit,
    Testsuite2Testcase,
    CollapseTransition,
  },
  mounted() {
    this.searchParams.creator = [this.$store.state.user.id];
    this.search();
    getProjectNames()
      .then((res) => {
        this.projects = res.data;
      })
      .catch((err) => {
        this.$Modal.error({
          title: "系统异常，请联系管理员……",
          content: JSON.stringify(err),
          closable: true,
        });
      });
    // 获取用户
    getUserNames()
      .then((res) => {
        this.users = res.data;
      })
      .catch((err) => {
        this.$Modal.error({
          title: "系统异常，请联系管理员……",
          content: JSON.stringify(err),
          closable: true,
        });
      });
  },
  data() {
    return {
      loading: false,
      showMore: false,
      createPeriodicTask: false,
      createTestsuite: false,
      editTestsuite: false,
      deleteTestsuiteConfirm: false,
      organizeTestcase: false,
      copyTestsuite: false,
      statusColor: {
        INITIAL: "#2db7f5",
        PASS: "#19be6b",
        PARTIAL_PASS: "#ff9900",
        FAIL: "#ed4014",
      },
      searchParams: {
        name: "",
        project: "",
        status: "",
        level: [],
        creator: [],
        enable_private_env: "",
      },
      testsuiteColumns: [
        {
          type: "selection",
          width: 60,
          align: "center",
          fixed: "left",
        },
        {
          title: "场景名称",
          key: "name",
          width: 350,
          tooltip: true,
        },
        {
          title: "所属项目",
          slot: "project",
          width: 350,
          ellipsis: true,
        },
        {
          title: "测试用例",
          slot: "testcases",
          width: 550,
        },
        {
          title: "场景全局参数",
          key: "global_variables",
          width: 350,
          ellipsis: true,
          align: "center",
        },
        {
          title: "开启/关闭私有环境",
          slot: "enable_private_env",
          width: 150,
          align: "center",
        },
        {
          title: "重要级别",
          slot: "level",
          align: "center",
          width: 120,
        },
        {
          title: "最近维护人",
          slot: "modifier",
          align: "center",
          width: 120,
        },
        {
          title: "状态",
          slot: "status",
          align: "center",
          width: 65,
          fixed: "right",
        },
        {
          title: "操作",
          slot: "action",
          width: 200,
          align: "center",
          fixed: "right",
        },
      ],
      testsuiteData: [],
      projects: [],
      project: {},
      testsuite: {},
      selectedTestsuites: [],
      levels: [
        { value: "LOW", label: "低" },
        { value: "NORMAL", label: "中" },
        { value: "HIGH", label: "高" },
        { value: "HIGHER", label: "更高" },
      ],
      users: [],
      periodicTask: "",
      periodicTaskArgs: "[]",
      page: {
        current: 1,
        total: 0,
        pageSize: 50,
        pageSizeOpts: [10, 30, 50, 100, 200],
      },
    };
  },
  methods: {
    reset() {
      this.searchParams = {
        name: "",
        project: "",
        status: "",
        level: [],
        creator: [],
        enable_private_env: "",
      };
      this.search();
    },
    search(page) {
      let data = {
        name: this.searchParams.name,
        project: this.searchParams.project,
        status: this.searchParams.status,
        level: this.searchParams.level.toString(),
        creator: this.searchParams.creator.toString(),
        enable_private_env: this.searchParams.enable_private_env,
        page: 1,
        page_size: this.page.pageSize,
      };
      if (typeof page == "number") {
        data.page = page;
      }
      this.page.current = data.page;

      getTestsuites(data)
        .then((res) => {
          const data = res.data;
          this.testsuiteData = data.results;
          this.page.total = data.count;
          if (data.next === null) {
            this.page.current = Math.ceil(this.page.total / this.page.pageSize);
          }
          if (data.previous === null) {
            this.page.current = 1;
          }
        })
        .catch((err) => {
          this.$Modal.error({
            title: "系统异常，请联系管理员……",
            content: JSON.stringify(err),
            closable: true,
          });
        });
    },
    change(val) {
      this.page.current = val;
      this.search(val);
    },
    pageSizeChange(val) {
      this.page.pageSize = val;
      this.search();
    },
    showEditTestsuiteModal(row) {
      let data = {
        project: row.project ? row.project.id : "",
        hasTestcase: row.testcases.length > 0,
      };
      let {
        id,
        name,
        remark,
        global_variables,
        enable_private_env,
        private_environment,
      } = row;
      Object.assign(data, {
        id,
        name,
        remark,
        global_variables,
        enable_private_env,
        private_environment,
      });
      this.testsuite = data;
      this.editTestsuite = true;
    },
    showBatchDeleteTestsuiteModal() {
      if (this.selectedTestsuites.length > 0) {
        this.deleteTestsuiteConfirm = true;
      } else {
        this.$Message.info("请选择需要删除的场景");
      }
    },
    showOrganizeTestcaseModal(row) {
      let { id, name } = row;
      this.testsuite = { id, name };
      this.project = row.project ? row.project : {};
      this.organizeTestcase = true;
    },
    selectionChange(val) {
      this.selectedTestsuites = val.map((item) => {
        return item.id;
      });
    },
    handleBatchExecTestsuite() {
      if (this.selectedTestsuites.length > 0) {
        let data = {
          testsuites: this.selectedTestsuites,
        };
        batchExecTestsuite(data).then((res) => {
          this.$Message.info(res.data);
          this.search();
        });
        return;
      }
      this.$Message.info("请选择需要执行的场景");
    },
    // 导出测试场景
    handleExportTestsuite() {
      if (this.selectedTestsuites.length > 0) {
        let data = {
          testsuite_ids: this.selectedTestsuites,
        };
        this.loading = true;
        exportTestsuite(data)
          .then((res) => {
            let blob = new Blob([res.data], {
              type: "application/vnd.ms-excel",
            });
            const blobUrl = window.URL.createObjectURL(blob);
            const elementLink = document.createElement("a");
            elementLink.download = "测试场景导出文档.xlsx";
            elementLink.style.display = "none";
            elementLink.href = blobUrl;
            // 触发点击
            document.body.appendChild(elementLink);
            elementLink.click();
            // 然后移除
            document.body.removeChild(elementLink);
            this.loading = false;
          })
          .catch((err) => {
            this.loading = false;
            this.$Message.info("导出场景失败，请重试……");
          });
        return;
      }
      this.$Message.info("请选择需要导出的场景");
    },
    handleDeleteTestsuiteConfirmCancel() {
      this.deleteTestsuiteConfirm = false;
      this.search();
      this.selectedTestsuites = [];
    },
    handleDeleteTestsuiteConfirmSubmit(unbundle) {
      let data = {
        unbundle: unbundle,
        testsuites: this.selectedTestsuites,
      };
      batchDeleteTestsuite(data)
        .then((res) => {
          this.$Message.info("删除成功");
          this.handleDeleteTestsuiteConfirmCancel();
        })
        .catch((err) => {
          this.$Modal.error({
            title: "系统异常，请联系管理员……",
            content: JSON.stringify(err),
            closable: true,
          });
        });
    },
    showCreatePeriodicTaskModal() {
      this.periodicTask =
        "批量执行测试场景:HttpAutoTestService.testsuite_task.batch_exec_testsuite";
      if (this.selectedTestsuites.length > 0) {
        let temp = JSON.stringify(this.selectedTestsuites).replace(/\"/g, "'");
        this.periodicTaskArgs = `["${temp}"]`;
        this.createPeriodicTask = true;
        return;
      }
      this.$Message.info("请选择需要创建定时任务的场景");
    },
    changeTestsuiteLevel(row) {
      const { id, level } = row;
      partialUpdateTestsuite({ id, level })
        .then((res) => {
          if (res.status === 200) {
            this.$Message.info("修改成功");
          } else {
            this.$Message.error("修改失败");
          }
        })
        .catch((err) => {
          this.$Modal.error({
            title: "系统异常，请联系管理员……",
            content: JSON.stringify(err),
            closable: true,
          });
        });
    },
    showCopyTestsuiteModal(id) {
      let testsuite = {
        id: id,
      };
      this.testsuite = testsuite;
      this.copyTestsuite = true;
    },
    switchEnablePrivateEnv(row) {
      const { id, enable_private_env } = row;
      partialUpdateTestsuite({ id, enable_private_env }).then((res) => {
        let status = res.status;
        if (status === 200) {
          this.$Message.info("切换开启/关闭私有环境成功");
        }
      });
    },
  },
};
</script>

<style scoped>
.levelSelect-prefix {
  width: 15px;
  height: 15px;
  border-radius: 50%;
}
.levelOption {
  color: #fff;
}
.levelOption-low {
  background-color: #2db7f5;
}
.levelOption-normal {
  background-color: #19be6b;
}
.levelOption-high {
  background-color: #ff9900;
}
.levelOption-higher {
  background-color: #ed4014;
}
.ivu-form-item {
  width: 100%;
}
</style>
